using System;
using System.Linq;
using CrazySname.GameClasses;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace CrazySname
{
    public class CrazySnake : Game
    {
        GraphicsDeviceManager _graphics;
        SpriteBatch _spriteBatch;

        private Texture2D _textura;
        private Keys _lastKeyPressed;
        private Cobra _cobra;
        private Alimento _alimento;
        private bool _gameIsOver;
        Keys[] _enableKeys;
        private int _pontos;
        const string VocePerdeu = "VOCE PERDEU";
        private SpriteFont _fontePontos;
        private Utilitarios _gameUtilitarios;
        int _lastTime = 0;
        const int RunSpeed = 130;

        private Texture2D _baixo;
        private Texture2D _cima;
        private Texture2D _esquerda;
        private Texture2D _direita;

        public Vector2 ScreenCenter
        {
            get
            {
#if !WINDOWS
                return new Vector2(GraphicsDevice.Viewport.Width / 2f, GraphicsDevice.Viewport.Height / 2f);
#else
                return new Vector2(Window.ClientBounds.Width / 2f, Window.ClientBounds.Height / 2f); 
#endif
            }
        }

        public CrazySnake()
        {
            _graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            _gameIsOver = false;
            _enableKeys = new[] { Keys.Left, Keys.Right, Keys.Up, Keys.Down };
            _gameUtilitarios = new Utilitarios();
            base.Initialize();
        }

        protected override void LoadContent()
        {
            _spriteBatch = new SpriteBatch(GraphicsDevice);
            _textura = Content.Load<Texture2D>("ponto");
            //Inicia a cobra no meio da tela
            _cobra = new Cobra(ScreenCenter.X, ScreenCenter.Y, _textura);
            _cobra.IniciaCobra();
            //Area que a cobra pode caminhar
            _cobra.SetarAreaDeCaminho(ScreenCenter.Y * 2, ScreenCenter.X * 2);
            //Inicio dizendo que o movimento vai ser para esquerda
            _lastKeyPressed = Keys.Left;
            //Inicia alimento
            _alimento = new Alimento(26, 16, _textura);
            _alimento.RandomizaAlimento(_cobra, _gameUtilitarios);

            //Phone setas
            _baixo = Content.Load<Texture2D>("direction_down");
            _cima = Content.Load<Texture2D>("direction_up");
            _esquerda = Content.Load<Texture2D>("direction_right");
            _direita = Content.Load<Texture2D>("direction_left");

            _cobra.FimDeJogo += FimDeJogo;
            _fontePontos = Content.Load<SpriteFont>("fonte");
        }

        protected override void UnloadContent()
        {
        }

        private void FimDeJogo()
        {
            _gameIsOver = true;
        }

        protected override void Update(GameTime gameTime)
        {
            var keyboardState = Keyboard.GetState();
            var pressedKeys = keyboardState.GetPressedKeys();

#if !WINDOWS
            Microsoft.Xna.Framework.Input.Touch.TouchCollection touchCollection = Microsoft.Xna.Framework.Input.Touch.TouchPanel.GetState();
            var measureString2 = fontePontos.MeasureString("Clique aqui para sair");
            var exitVector = new Vector2(ScreenCenter.X * 2 - measureString2.X, 0);
            if (touchCollection.Count > 0)
                if (touchCollection[0].Position.X > exitVector.X && touchCollection[0].Position.Y > exitVector.Y)
                    Exit();

            if (touchCollection.Count > 0)
            {
                if (TocouSetaCima(touchCollection))
                    pressedKeys = new[] { Keys.Up };

                else if (TocouSetaBaixo(touchCollection))
                    pressedKeys = new[] { Keys.Down };

                else if (TocouSetaDireita(touchCollection))
                    pressedKeys = new[] { Keys.Right };

                else if (TocouSetaEsquerda(touchCollection))
                    pressedKeys = new[] { Keys.Left };
            }
#endif
            if (pressedKeys.Contains(Keys.Escape))
                Exit();

            if (!_gameIsOver)
            {
                int currentTime = Environment.TickCount;
                if (currentTime - _lastTime > RunSpeed)
                {
                    _lastTime = currentTime;
                    _cobra.AtualizaMovimento(_lastKeyPressed, _gameUtilitarios);
                    if (_cobra.CobraComeuAlimento(_alimento, _gameUtilitarios))
                    {
                        _alimento.RandomizaAlimento(_cobra, _gameUtilitarios);
                        _cobra.AdicionaParte(_cobra.Partes[_cobra.Partes.Count - 1]);
                        _pontos += 20;
                    }
                }
            }

            if (pressedKeys.Count() > 0 && _enableKeys.Contains(pressedKeys[0]))
                _lastKeyPressed = pressedKeys[0];

            base.Update(gameTime);
        }

#if !WINDOWS
        private bool TocouSetaEsquerda(Microsoft.Xna.Framework.Input.Touch.TouchCollection touchCollection)
        {
            return (touchCollection[0].Position.Y > ScreenCenter.Y - direita.Height / 2f && touchCollection[0].Position.Y < ScreenCenter.Y + direita.Height / 2f) &&
                (touchCollection[0].Position.X > 0 && touchCollection[0].Position.X < 0 + cima.Width);
        }

        private bool TocouSetaDireita(Microsoft.Xna.Framework.Input.Touch.TouchCollection touchCollection)
        {
            return (touchCollection[0].Position.Y > ScreenCenter.Y - direita.Height / 2f && touchCollection[0].Position.Y < ScreenCenter.Y + direita.Height / 2f) &&
                (touchCollection[0].Position.X > ScreenCenter.X * 2 - cima.Width && touchCollection[0].Position.X < ScreenCenter.X * 2);
        }

        private bool TocouSetaBaixo(Microsoft.Xna.Framework.Input.Touch.TouchCollection touchCollection)
        {
            return (touchCollection[0].Position.Y > ScreenCenter.Y * 2 - baixo.Height && touchCollection[0].Position.Y < ScreenCenter.Y * 2) &&
                   (touchCollection[0].Position.X > ScreenCenter.X - baixo.Width / 2f && touchCollection[0].Position.X < ScreenCenter.X + baixo.Width / 2f);
        }

        private bool TocouSetaCima(Microsoft.Xna.Framework.Input.Touch.TouchCollection touchCollection)
        {
            return (touchCollection[0].Position.Y > 0 && touchCollection[0].Position.Y < cima.Height) &&
                   (touchCollection[0].Position.X > ScreenCenter.X - (cima.Width / 2f) && touchCollection[0].Position.X < ScreenCenter.X + (cima.Width / 2f));
        } 
#endif

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            _spriteBatch.Begin();
            _cobra.Desenhar(_spriteBatch);
            _alimento.Desenhar(_spriteBatch);
            _spriteBatch.DrawString(_fontePontos, string.Format("Pontos: {0}", _pontos), new Vector2(0, 0), Color.Black);
            if (_gameIsOver)
            {
                Vector2 measureString = _fontePontos.MeasureString(VocePerdeu);
                var msgPosition = new Vector2(ScreenCenter.X - measureString.X / 2, ScreenCenter.Y - measureString.Y / 2);
                _spriteBatch.DrawString(_fontePontos, VocePerdeu, msgPosition, Color.Black);
            }
#if !WINDOWS
            var transparente = new Color(50, 50, 50, 0);
            var vec = new Vector2(ScreenCenter.X - (cima.Width / 2f), 0);
            spriteBatch.Draw(cima, vec, transparente);

            vec = new Vector2(ScreenCenter.X - (cima.Width / 2f), ScreenCenter.Y * 2 - baixo.Height);
            spriteBatch.Draw(baixo, vec, transparente);

            vec = new Vector2(0, ScreenCenter.Y - direita.Height / 2f);
            spriteBatch.Draw(direita, vec, transparente);

            vec = new Vector2(ScreenCenter.X * 2 - esquerda.Width, ScreenCenter.Y - esquerda.Width / 2f);
            spriteBatch.Draw(esquerda, vec, transparente);

            var measureString2 = fontePontos.MeasureString("Clique aqui para sair");
            var msgPosition2 = new Vector2(ScreenCenter.X * 2 - measureString2.X, 0);
            spriteBatch.DrawString(fontePontos, "Clique aqui para sair", msgPosition2, Color.Black);
#endif
            _spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}
